/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package company.beans;

import company.folder.qualifiers.SeeAllProfilesEvent;
import entities.Candidate;
import entities.Company;
import entities.CompanyAdquiredProfile;
import entities.CompanyAdquiredProfileFolder;
import entities.CompanyFolder;
import entities.Search;
import facades.CompanyAdquiredProfileFacade;
import facades.CompanyAdquiredProfileFolderFacade;
import facades.CompanyFacade;
import facades.CompanyFolderFacade;
import facades.CompanyFolderTypeFacade;
import facades.SearchFacade;
import javax.inject.Named;
import javax.enterprise.context.SessionScoped;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;
import javax.annotation.PostConstruct;
import javax.enterprise.event.Event;
import javax.enterprise.event.Observes;
import javax.enterprise.event.TransactionPhase;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.transaction.Transactional;
import qualifiers.ChosenEntityEvent;
import qualifiers.CreatedEntityEvent;
import qualifiers.EditedEntityEvent;
import qualifiers.LoggedIn;

/**
 *
 * @author damianfernandez
 */
@Named(value = "bagBean")
@SessionScoped
public class BagBean implements Serializable {
    @Inject
    @LoggedIn
    private Company company;
    private List<Candidate> selectedCandidates;
    private CompanyFolder folder;
    private Search search;
    @Inject
    private CompanyAdquiredProfileFacade companyAdquiredProfileFacade;
    @Inject
    private CompanyAdquiredProfileFolderFacade companyAdquiredProfileFolderFacade;
    @Inject
    @CreatedEntityEvent
    private Event<CompanyAdquiredProfile>  createdCompanyAdquiredProfileEvent;
    @Inject
    @CreatedEntityEvent
    private Event<CompanyAdquiredProfileFolder>  createdCompanyAdquiredProfileFolderEvent;
    @Inject
    @EditedEntityEvent
    private Event<Search> editedSearchEvent;
    @Inject
    @CreatedEntityEvent
    private Event<CompanyFolder> createdCompanyFolderEvent;
    @Inject
    @EditedEntityEvent
    private Event<CompanyFolder> editedCompanyFolderEvent;
    @Inject
    @ChosenEntityEvent
    private Event<CompanyFolder> chosenCompanyFolderEvent;
    @Inject
    CompanyFolderFacade companyFolderFacade;
    @Inject
    CompanyFolderTypeFacade companyFolderTypeFacade;
    private Boolean dontWantToPersistSearch;
    @Inject
    private CompanyFacade companyFacade;
    @Inject
    private SearchFacade searchFacade;
    private Candidate selectedCandidate;
    @Inject
    @SeeAllProfilesEvent
    Event<Integer> seeAllProfilesEvent;
    
    @PostConstruct
    public void init(){
        dontWantToPersistSearch=false;
        selectedCandidates=new ArrayList<Candidate>();
    }
    
    public void reinitBean(){
        dontWantToPersistSearch=false;
    }
    
    public void addCandidate(Candidate c){
        if(company.getAvailableCredits()>selectedCandidates.size()){
            if(!selectedCandidates.contains(c)){
                getSelectedCandidates().add(c);
            } 
        }
        else{
            noCreditsAvailable();
        }
    }
    
    public void removeCandidate(Candidate c){
        selectedCandidates.remove(c);
    }

    /**
     * @return the selectedCandidates
     */
    public List<Candidate> getSelectedCandidates() {
        return selectedCandidates;
    }

    /**
     * @param selectedCandidates the selectedCandidates to set
     */
    public void setSelectedCandidates(List<Candidate> selectedCandidates) {
        this.selectedCandidates = selectedCandidates;
    }

    /**
     * @return the folder
     */
    public CompanyFolder getFolder() {
        return folder;
    }

    /**
     * @param folder the folder to set
     */
    public void setFolder(CompanyFolder folder) {
        this.folder = folder;
    }

    /**
     * @return the search
     */
    public Search getSearch() {
        return search;
    }

    /**
     * @param search the search to set
     */
    public void setSearch(Search search) {
        this.search = search;
    }
    
    public void onEditedCompany(@Observes(during = TransactionPhase.AFTER_SUCCESS) @EditedEntityEvent Company company){
        this.company=company;
    }
    
    @Transactional
    public String recruit(){
        Boolean editSearch=false;
        String redirect =null;
        if(company.getAvailableCredits()>selectedCandidates.size()){
            if(search.getFolder()!=null){
                search.setFolder(company.getCompanyFolderList().get(company.getCompanyFolderList().indexOf(search.getFolder())));
            }
            if(!dontWantToPersistSearch){
                if(search.getIdSearch()==null){
                    createNewSearch();
                }
                else{
                    editSearch=true;
                }
                for (Candidate selectedCandidateIteration : selectedCandidates) {
                    CompanyAdquiredProfile adquiredProfile=getAdquiredProfileIfExists(selectedCandidateIteration);
                    CompanyAdquiredProfileFolder companyAdquiredProfileFolder;
                    if(adquiredProfile==null){
                        adquiredProfile=createCompanyAdquiredProfile(selectedCandidateIteration);
                        companyAdquiredProfileFolder=createCompanyAdquiredProfileFolder(adquiredProfile, search.getFolder());
                        if(adquiredProfile.getCompanyAdquiredProfileFolderList()==null){
                            adquiredProfile.setCompanyAdquiredProfileFolderList(new ArrayList<CompanyAdquiredProfileFolder>());
                        }
                        adquiredProfile.getCompanyAdquiredProfileFolderList().add(companyAdquiredProfileFolder);
                        if(search.getFolder().getCompanyAdquiredProfileFolderList()==null){
                            search.getFolder().setCompanyAdquiredProfileFolderList(new ArrayList<CompanyAdquiredProfileFolder>());
                        }
                        search.getFolder().getCompanyAdquiredProfileFolderList().add(companyAdquiredProfileFolder);
                        company.getCompanyAdquiredProfileList().add(adquiredProfile);
                        company.setAvailableCredits(company.getAvailableCredits()-1);
                    }
                    else if(search.getFolder()!=null){
                        companyAdquiredProfileFolder=getAdquiredProfileFolderIfExists(adquiredProfile,search.getFolder());
                        if(companyAdquiredProfileFolder==null){
                           companyAdquiredProfileFolder=createCompanyAdquiredProfileFolder(adquiredProfile, search.getFolder());
                           if(adquiredProfile.getCompanyAdquiredProfileFolderList()==null){
                                adquiredProfile.setCompanyAdquiredProfileFolderList(new ArrayList<CompanyAdquiredProfileFolder>());
                            }
                            adquiredProfile.getCompanyAdquiredProfileFolderList().add(companyAdquiredProfileFolder);
                            if(search.getFolder().getCompanyAdquiredProfileFolderList()==null){
                                search.getFolder().setCompanyAdquiredProfileFolderList(new ArrayList<CompanyAdquiredProfileFolder>());
                            }
                            search.getFolder().getCompanyAdquiredProfileFolderList().add(companyAdquiredProfileFolder);
                        }
                        Collections.replaceAll(company.getCompanyAdquiredProfileList(), adquiredProfile, adquiredProfile);
                    }
                }
                redirect="/views/company/folder/NewViewAllProfilesView?faces-redirect=true";
                if(editSearch){
                    searchFacade.edit(search);
                    editedSearchEvent.fire(search);
                }
                if(search.getFolder()!=null){
                    Collections.replaceAll(company.getCompanyFolderList(), search.getFolder(), search.getFolder());
                    editedCompanyFolderEvent.fire(search.getFolder());
                    chosenCompanyFolderEvent.fire(search.getFolder());
                    redirect="/views/company/folder/NewViewFolderView?faces-redirect=true";
                }
                companyFacade.edit(company);
                //editedCompanyEvent.fire(company);
                selectedCandidates=new ArrayList<Candidate>();
                dontWantToPersistSearch=false;
            }
            else{
                redirect=recruitWithoutSearch();
            }
        }
        else{
            noCreditsAvailable();
        }
        return redirect;
    }
    
    private CompanyAdquiredProfile getAdquiredProfileIfExists(Candidate selectedCandidateAP){
        CompanyAdquiredProfile adquiredProfile=null;
        if(company.getCompanyAdquiredProfileList()!=null){
            for (CompanyAdquiredProfile companyAdquiredProfile : company.getCompanyAdquiredProfileList()) {
                if(companyAdquiredProfile.getCandidate().equals(selectedCandidateAP)){
                    adquiredProfile=companyAdquiredProfile;
                    break;
                }
            } 
        }
        return adquiredProfile;
    }
    
    private CompanyAdquiredProfileFolder getAdquiredProfileFolderIfExists(CompanyAdquiredProfile adquiredProfile, CompanyFolder companyFolder){
        CompanyAdquiredProfileFolder companyAdquiredProfileFolder=null;
        if(adquiredProfile.getCompanyAdquiredProfileFolderList()!=null){
            for (CompanyAdquiredProfileFolder companyAdquiredProfileFolderIt : adquiredProfile.getCompanyAdquiredProfileFolderList()) {
                if(companyAdquiredProfileFolderIt.getCompanyFolder().equals(companyFolder)){
                    companyAdquiredProfileFolder=companyAdquiredProfileFolderIt;
                    break;
                }
            }
        }
        return companyAdquiredProfileFolder;
    }
    
    @Transactional
    public String recruitWithoutSearch(){
        String redirect =null;
        if(folder!=null){
            folder=company.getCompanyFolderList().get(company.getCompanyFolderList().indexOf(folder));
        }
        if(company.getAvailableCredits()>selectedCandidates.size()){
            for (Candidate selectedCandidateIteration : selectedCandidates) {
                CompanyAdquiredProfile adquiredProfile=getAdquiredProfileIfExists(selectedCandidateIteration);
                CompanyAdquiredProfileFolder companyAdquiredProfileFolder;
                if(adquiredProfile==null){
                    adquiredProfile=createCompanyAdquiredProfile(selectedCandidateIteration);
                    if(folder!=null){
                        companyAdquiredProfileFolder=createCompanyAdquiredProfileFolder(adquiredProfile,folder);
                        if(adquiredProfile.getCompanyAdquiredProfileFolderList()==null){
                            adquiredProfile.setCompanyAdquiredProfileFolderList(new ArrayList<CompanyAdquiredProfileFolder>());
                        }
                        adquiredProfile.getCompanyAdquiredProfileFolderList().add(companyAdquiredProfileFolder);
                        if(folder.getCompanyAdquiredProfileFolderList()==null){
                                folder.setCompanyAdquiredProfileFolderList(new ArrayList<CompanyAdquiredProfileFolder>());
                        }
                        folder.getCompanyAdquiredProfileFolderList().add(companyAdquiredProfileFolder);
                    }
                    company.getCompanyAdquiredProfileList().add(adquiredProfile);
                    company.setAvailableCredits(company.getAvailableCredits()-1);
                }
                else if(folder!=null){
                    companyAdquiredProfileFolder=getAdquiredProfileFolderIfExists(adquiredProfile,folder);
                    if(companyAdquiredProfileFolder==null){
                        companyAdquiredProfileFolder=createCompanyAdquiredProfileFolder(adquiredProfile, folder);
                        if(adquiredProfile.getCompanyAdquiredProfileFolderList()==null){
                            adquiredProfile.setCompanyAdquiredProfileFolderList(new ArrayList<CompanyAdquiredProfileFolder>());
                        }
                        adquiredProfile.getCompanyAdquiredProfileFolderList().add(companyAdquiredProfileFolder);
                        if(folder.getCompanyAdquiredProfileFolderList()==null){
                            folder.setCompanyAdquiredProfileFolderList(new ArrayList<CompanyAdquiredProfileFolder>());
                        }
                        folder.getCompanyAdquiredProfileFolderList().add(companyAdquiredProfileFolder);
                    }
                    Collections.replaceAll(company.getCompanyAdquiredProfileList(), adquiredProfile, adquiredProfile);
                }
            }
            companyFacade.edit(company);
            //editedCompanyEvent.fire(company);
            redirect="/views/company/folder/NewViewFolderView?faces-redirect=true";
            if(folder==null){
                redirect="/views/company/folder/NewViewAllProfilesView?faces-redirect=true";
                seeAllProfilesEvent.fire(0);
            }
            else{
                Collections.replaceAll(company.getCompanyFolderList(), folder, folder);
                editedCompanyFolderEvent.fire(folder);
                chosenCompanyFolderEvent.fire(folder);
            }
            selectedCandidates=new ArrayList<Candidate>();
            dontWantToPersistSearch=false;
            folder=null;
        }
        else{
            noCreditsAvailable();
        }
        return redirect;
    }
    
    @Transactional
    private CompanyAdquiredProfile createCompanyAdquiredProfile(Candidate candidate){
        CompanyAdquiredProfile adquiredProfile=new CompanyAdquiredProfile();
        Date currentDate=new Date();
        adquiredProfile.setAdquisitionDate(currentDate);
        adquiredProfile.setPayDate(currentDate);
        adquiredProfile.setIsPayed(true);
        adquiredProfile.setPrice(BigDecimal.ZERO);
        adquiredProfile.setCandidate(candidate);
        adquiredProfile.setCompany(company);
        companyAdquiredProfileFacade.create(adquiredProfile);
        createdCompanyAdquiredProfileEvent.fire(adquiredProfile);
        return adquiredProfile;
    }
    
    @Transactional
    private CompanyAdquiredProfileFolder createCompanyAdquiredProfileFolder(CompanyAdquiredProfile profile, CompanyFolder folder){
        CompanyAdquiredProfileFolder companyAdquiredProfileFolder=new CompanyAdquiredProfileFolder();
        companyAdquiredProfileFolder.setCompanyAdquiredProfile(profile);
        companyAdquiredProfileFolder.setCompanyFolder(folder);
        companyAdquiredProfileFolder.setCreationDate(new Date());
        companyAdquiredProfileFolderFacade.create(companyAdquiredProfileFolder);
        if(profile.getCompanyAdquiredProfileFolderList()==null){
            profile.setCompanyAdquiredProfileFolderList(new ArrayList<CompanyAdquiredProfileFolder>());
        }
        createdCompanyAdquiredProfileFolderEvent.fire(companyAdquiredProfileFolder);
        return companyAdquiredProfileFolder;
    }        
    
    @Transactional
    public void createNewSearch(){
        boolean newFolder=false;
        if(search.getFolder()==null){
            newFolder=true;
            CompanyFolder folderSearch=new CompanyFolder();
            folderSearch.setCompanyAdquiredProfileFolderList(new ArrayList<CompanyAdquiredProfileFolder>());
            folderSearch.setCompanyAdquiredProfileList(new ArrayList<CompanyAdquiredProfile>());
            folderSearch.setCompanyFolderType(companyFolderTypeFacade.getNormalFolderType());
            folderSearch.setCreationDate(new Date());
            folderSearch.setDescription(search.getDescription());
            folderSearch.setIdCompany(company);
            folderSearch.setSearchList(new ArrayList<Search>());
            folderSearch.getSearchList().add(search);
            search.setFolder(folderSearch);
        }
        else{
            if(search.getFolder().getSearchList()==null){
                search.getFolder().setSearchList(new ArrayList<Search>());
            }
            search.getFolder().getSearchList().add(search);
        }
        search.setActive(true);
        search.setCompany(company);
        search.setCreateDate(new Date());
        search.setLastSearchDate(new Date());
        searchFacade.create(search);
        if(company.getSearchList()==null){
            company.setSearchList(new ArrayList<Search>());
        }
        company.getSearchList().add(search);
        if(newFolder){
            if(company.getCompanyFolderList()==null){
                company.setCompanyFolderList(new ArrayList<CompanyFolder>());
            }
            company.getCompanyFolderList().add(search.getFolder());
            createdCompanyFolderEvent.fire(search.getFolder());
        }
    }
    
    private void noCreditsAvailable(){
        FacesContext context = FacesContext.getCurrentInstance();
        Locale locale=context.getViewRoot().getLocale();
        ResourceBundle rb = ResourceBundle.getBundle("messages", locale);
        String successMessage=rb.getString("NoCreditsAvailable");
        FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, successMessage, successMessage);  
        context.addMessage(null, message); 
        context.renderResponse();
    }
    
    /**
     * @return the dontWantToPersistSearch
     */
    public Boolean getDontWantToPersistSearch() {
        return dontWantToPersistSearch;
    }

    /**
     * @param dontWantToPersistSearch the dontWantToPersistSearch to set
     */
    public void setDontWantToPersistSearch(Boolean dontWantToPersistSearch) {
        this.dontWantToPersistSearch = dontWantToPersistSearch;
    }
    
    public String redirectToBag(){
        String redirect="/views/company/BagView?faces-redirect=true";
        return redirect;
    }
    
    public String redirectToSearchBag(){
        String redirect="/views/company/BagSearchView?faces-redirect=true";
        return redirect;
    }

    /**
     * @return the company
     */
    public Company getCompany() {
        return company;
    }

    /**
     * @param company the company to set
     */
    public void setCompany(Company company) {
        this.company = company;
    }

    /**
     * @return the selectedCandidate
     */
    public Candidate getSelectedCandidate() {
        return selectedCandidate;
    }

    /**
     * @param selectedCandidate the selectedCandidate to set
     */
    public void setSelectedCandidate(Candidate selectedCandidate) {
        this.selectedCandidate = selectedCandidate;
    }
    
}
